﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mogre;
using MogreNewt;

namespace WastedMechanics
{
    public class HingedDoor : Door
    {
        public enum DoorDirection
        {
            Inward,
            Outward
        }

        public HingedDoorProfile Profile;

        public SceneNode Node;
        public Entity Entity;
        public Body Body;

        Vector3 HingeOffset;
        Vector3 HingePosition;
        float Phase;
        public DoorDirection Direction;

        public HingedDoor(HingedDoorProfile profile)
        {
            Profile = profile.Clone();
            ShowName = true;
            IsObstacle = true;
            Direction = DoorDirection.Inward;

            Entity = Engine.SceneManager.CreateEntity(Profile.MeshName);
            Node = Engine.SceneManager.RootSceneNode.CreateChildSceneNode();
            Node.AttachObject(Entity);

            Vector3 scaledSize = Entity.BoundingBox.Size * Profile.BodyScaleFactor;
            HingeOffset = scaledSize * Vector3.UNIT_X * 0.5f;

            ConvexCollision collision = new MogreNewt.CollisionPrimitives.Box(
                Engine.NewtonWorld,
                scaledSize,
                Quaternion.IDENTITY,
                Engine.GetUniqueBodyId());
            
            Body = new Body(Engine.NewtonWorld, collision, false);
            Body.AttachNode(Node);
            Body.SetMassMatrix(0,Vector3.ZERO);            
            
            Body.UserData = this;
            Body.MaterialGroupID = Engine.MaterialManager.Materials["Described"];
            
            collision.Dispose();
            
        }

        
        public void UpdatePosition()
        {
            Degree angle = Helper.CosInterpolate(0.0f, Profile.MaxAngle.ValueDegrees, Phase);
            if (Direction == DoorDirection.Outward)
                angle *= -1.0f;
            Quaternion rotation = BaseOrientation * Helper.QuaternionFromAngle(angle, Vector3.UNIT_Y);
            Vector3 position = HingePosition + rotation * HingeOffset;
            Body.Velocity = (position - Body.Position);
            Body.SetPositionOrientation(position, rotation);
            
        }
        
        public override void Update()
        {
            if (State != DoorState.Idle)
            {                
                if (State == DoorState.Opening)
                {
                    Phase += Profile.Speed;
                    if (Phase >= 1.0f)
                    {
                        Phase = 1.0f;
                        State = DoorState.Idle;
                        IsOpen = true;
                    }
                }
                else if (State == DoorState.Closing)
                {
                    Phase -= Profile.Speed;
                    if (Phase <= 0.0f)
                    {
                        Phase = 0.0f;
                        State = DoorState.Idle;
                        IsOpen = false;
                    }
                }                
            }
            UpdatePosition();
        }

        public override void Destroy()
        {
            base.Destroy();
        }

        public override string Description
        {
            get
            {
                return Profile.Description;
            }
            set
            {
                Profile.Description = value;
            }
        }

        public override string DisplayName
        {
            get
            {
                return "(door)";
            }
            set
            {
            }
        }

        public override Vector3 DisplayNameOffset
        {
            get
            {
                return Vector3.ZERO;
            }
            set
            {
            }
        }

        public override Vector3 Position
        {
            get
            {
                return Body.Position;
            }
            set
            {
                BasePosition = value;
                HingePosition = BasePosition - BaseOrientation * HingeOffset;
                UpdatePosition();                
            }
        }

        public override Quaternion Orientation
        {
            get
            {
                return BaseOrientation;
            }
            set
            {
                BaseOrientation = value;
                HingePosition = BasePosition - BaseOrientation * HingeOffset;
                UpdatePosition();                                         
            }
        }
    }
}
